package juc.topic;

/**
 * 写两个线程轮流打印1-100，交替打印
 */
public class AlternatePrinting {
    private int num = 1;
    private final Object lock = new Object();
    public static void main(String[] args) {
        AlternatePrinting ap = new AlternatePrinting();
        // 奇数线程
        new Thread(()-> {
            ap.print(true);
            },"奇数线程").start();

        // 偶数线程
        new Thread(()-> {
            ap.print(false);
        },"偶数线程").start();
    }


    /**
     *
     * @param flag true 奇数线程，false 偶数线程
     */
    private void print(boolean flag) {
        System.out.println("尝试获取锁的线程：" + Thread.currentThread().getName() + " : " + num);
        while(num <= 100){
            synchronized (lock) {
                System.out.println("获取到锁的线程：" + Thread.currentThread().getName() + " : " + num);
                //使用 while 而不是 if 是为了确保线程在等待条件满足时能够持续检查条件，而不是只检查一次。
                // 具体来说，while 循环会在线程被唤醒后再次检查条件，以确保线程在继续执行之前条件仍然满足。
                //如果使用 if 语句，线程在被唤醒后只会检查一次条件，如果条件不满足，线程可能会错误地继续执行，这会导致线程交替打印的逻辑出现问题。
                //简单点说就是条件不满足就继续等待，条件满足就执行业务逻辑。
                while ((flag && num % 2 == 0) || (!flag && num % 2 == 1)) {
                    try {
                        // 如果当前线程不应该打印,等待
                        System.out.println("当前线程不应该打印等待：" + Thread.currentThread().getName() + " : " + num);
                        lock.wait();//会释放锁，进入等待状态
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
                if (num <= 100) {
                    System.out.println(Thread.currentThread().getName() + " : " + num);
                    num++;
                    // 唤醒其他线程
                    lock.notifyAll();//唤醒所有等待的线程
                }

            }
        }

    }
}
